/*
 * @: 
 * @Version: 1.0
 * @Autor: ziwei
 * @Date: 2021-11-29 14:32:23
 * @LastEditors: ziwei
 * @LastEditTime: 2021-12-02 18:05:12
 */
import React from "react";
import ReactDOM from 'react-dom';
import {createStore,combineReducers,applyMiddleware} from 'redux'
import createSagaMiddleware from "redux-saga";
import * as sagaEffects from 'redux-saga/effects';
import { Provider,connect } from "react-redux";
import prefixNamespace from "./prefixNameSpace";
import {NAMESPACE_SEP} from './constant';
import {createHashHistory} from 'history';
import {ConnectedRouter,connectedRouter,routerMiddleware} from 'connected-react-router'
let history = createHashHistory();
export {connect}
function dva(){
  debugger
  const app={
    _models:[],//存放model的数组
    model,//函数用来往model数组中添加model元素
    router,//定义路由的函数
    _router:null,//存放路由函数的变量
    start//开启渲染
  }
  function model(modelObject){
    const prefixModel = prefixNamespace(modelObject)
    app._models.push(modelObject);
  }
  function router(routerConfig) {
    app._router = routerConfig
  }
  //将reducer定义成函数
  //1 合并connectRouter这个reducer
  let initialReducers = {router:connectedRouter(history)}
  function start(selector) {
    for(const model of app._models){
      initialReducers[model.namespace] = getReducer(model)
    }
    let rootReducer = createReducer();
    let sagas = getSagas(app)
    let sagaMiddleware = createSagaMiddleware()
    let store = applyMiddleware(sagaMiddleware,routerMiddleware(history))(createStore)(rootReducer)
    sagas.forEach(sagaMiddleware.run)
    ReactDOM.render(
      <Provider store={store}>
        {app._router()}
      </Provider>,document.querySelector(selector)
    )
  }
  //把每个model中的effects变成saga 最后统一交给run方法执行
  function getSagas(app) {
    let sagas = [];
    for(let model of app._models){
      sagas.push(getSaga(model.effect,model))
    }
    return sagas
  }
  function createReducer(params) {
    console.log("initialReducersinitialReducers",initialReducers)
    return combineReducers(initialReducers)
  }
  return app
}

//saga 是generate
function getSaga(effects,model) {
  return function *() {
    for(const key in effects){
      //每个key转成一个watcherSaga,然后开启一个子进程去执行
      const watcherSaga = getWatcher(key,model.effects[key],model);
      //开启一个子进程单独执行
      yield sagaEffects.fork(watcherSaga);
    }
  }
}

function getWatcher(key,effect,model) {
  return function *() {
    yield sagaEffects.takeEvery(key,function *(action) {
      yield effect(action,{
        ...sagaEffects,put:action=>sagaEffects.put({...action,type:prefixType(action.type,model)})
      })
    })
  }
}
function prefixType(type,model) {
  if(type.indexOf('/'===-1)){
    return `${model.namespace}${NAMESPACE_SEP}${type}`;//counter/asyncAdd
  }else{
    console.log(`Warning:[sagaEffects.put] counter/add should not be predixed with namespace ${model.namespace}`);
    return type
  } 
}
/* 
转成格式

*/
function getReducer(model) {
  let {state:initialState,reducers} = model;
  return (state=initialState,action)=>{
    console.log("reducers",action);
    let reducer = reducers[action.type];
    if(reducer) return reducer(state,action);
    return state
  }
}

export default dva

/*  

connect =》 Provider
Provider =>store
store=>reducer
获取每个model的reducers对象，把每个对象变成一个函数
通过combineReducers合并一个reducer
*/
